#Sydney Map

import sys
import urllib
from copy import copy
from os import path, unlink
from subprocess import Popen, PIPE

class ProcessError(Exception): pass

# Manually download shapefile layers, since they are infrequently updated:
#wget http://tile.openstreetmap.org/world_boundaries-spherical.tgz
#wget http://hypercube.telascience.org/~kleptog/processed_p.zip

# restrictedExtent: new OpenLayers.Bounds(16770012,-4044490,16876903,-3980726)
# maxExtent: new OpenLayers.Bounds(-20000000,-20000000,20000000,20000000),

_settings = {
    'debug': True,
    'dbname': 'aussie',
    'dbprefix': 'osm_au',
    'dbuser': 'postgres',
    'dbpass': '',
    #'sharedir':'/usr/share/postgresql-8.3-postgis',
    #'sharedir':'/usr/local/pgsql/share',
    'sharedir':'/usr/share/postgresql/8.3/contrib/',
    'tmp_sql': '/tmp/run_this.sql',
    'merc_proj4':'+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ',
    'style': '/Users/spring/src/osm2pgsql/default.style',
    #'style':'/home/dane/src/osm2pgsql/default.style',
    'osm_url':'http://downloads.cloudmade.com/north_america/united_states/washington/washington.osm.bz2',
    #'osm_url':'http://downloads.cloudmade.com/oceania/australia/australia.osm.bz2',
    'sqlitedb':'sydney2.sqlite',
    'sqlite_select': ''' "select * from %s WHERE way && SetSRID('BOX3D(16770012 -4044490,16876903 -3980726)'::box3d,900913)" '''
    }

settings = {
    'debug': True,
    'dbname': 'osm_roadflaw',
    'dbprefix': 'osm_wa',
    'dbuser': 'postgres',
    'dbpass': '',
    'sharedir':'/usr/share/postgresql/8.3/contrib',
    'tmp_sql': '/tmp/run_this.sql',
    'merc_proj4':'+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ',
    'style':'/home/dane/src/osm2pgsql/default.style',
    'osm_url':'http://downloads.cloudmade.com/north_america/united_states/washington/washington.osm.bz2',
    }
    
table_names = ['line','point','polygon','roads']
tables = ['%s_%s' % (settings['dbprefix'],t) for t in table_names]
#tables.extend(['rels','nodes','ways'])

from mapnik import Projection as P, Envelope as E
p = P(settings['merc_proj4'])
bbox = '16770012,-4044490,16876903,-3980726'
coords = [int(i) for i in bbox.split(',')]
lonlat_bbox = p.inverse(E(*coords))
#settings['import_bbox'] = lonlat_bbox.to_string()

SKIP_ALL = False
RUN_STEPS = range(1,8+1)
if SKIP_ALL:
    RUN_STEPS = [999999] 
STEP = 1
RE_DOWNLOAD = False

increments = [.1*i for i in range(1,10)]

def msg(message):
    if settings['debug']:
        print message

def reporter(count,block_size,total_size):
    complete = round(count*block_size*1.0/total_size,2)
    #if complete % 1000 == 0:
    if complete in increments:
        msg('%s percent downloaded' % int(complete*100))
        increments.remove(complete)

def pull_down(url,filename=None):
    global STEP
    if not filename:
       filename = url.split('/')[-1]
    if STEP in RUN_STEPS:
        if path.exists(filename) and path.isfile(filename):
            if RE_DOWNLOAD:
                unlink(filename)
            else:
                return filename
        f = open(filename,'w+b')
        msg('downloading %s' % filename)
        urllib.urlretrieve(url,filename,reporter)
        urllib.urlcleanup()
        f.close()
        return filename
    else:
        msg('skipping step #%s: %s' %  (STEP,'downloading %s' % filename))
    STEP += 1

def write_tmp_sql(sql):
    srs = open(settings['tmp_sql'],'w')
    srs.write(sql)
    srs.close()

def call(cmd,fatal=True):
    global STEP
    if STEP in RUN_STEPS:
        stdin, stderr = Popen(cmd,shell=True,stdout=PIPE,stderr=PIPE).communicate()
        if not stderr:
            msg('%s successful... %s' % (cmd,stdin.strip()))
        else:
            if fatal:
                sys.exit('%s failed: %s' % (cmd,stderr))
            else:
                msg('%s failed: %s' % (cmd,stderr))
    else:
        msg('skipping step #%s: %s' %  (STEP,cmd))
    STEP += 1

# 1
call('dropdb -U %(dbuser)s %(dbname)s' % settings,fatal=False)

# 2
call('createdb -E UTF8 -U %(dbuser)s %(dbname)s' % settings)

# 3
call('createlang plpgsql -U %(dbuser)s %(dbname)s' % settings)

# 4
call('psql -U %(dbuser)s -f %(sharedir)s/lwpostgis.sql %(dbname)s' % settings,fatal=False)

# 5
call('psql -U %(dbuser)s -f %(sharedir)s/spatial_ref_sys.sql %(dbname)s' % settings,fatal=False)

merc_prj = """
INSERT into spatial_ref_sys (srid, auth_name, auth_srid, proj4text, srtext) values ( 900913, 'sr-org', 900913, '%(merc_proj4)s', 'PROJCS["Google Mercator",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137.0,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0.0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.017453292519943295],AXIS["Geodetic latitude",NORTH],AXIS["Geodetic longitude",EAST],AUTHORITY["EPSG","4326"]],PROJECTION["Mercator_1SP"],PARAMETER["semi_minor",6378137.0],PARAMETER["latitude_of_origin",0.0],PARAMETER["central_meridian",0.0],PARAMETER["scale_factor",1.0],PARAMETER["false_easting",0.0],PARAMETER["false_northing",0.0],UNIT["m",1.0],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","900913"]]')
""" % settings

write_tmp_sql(merc_prj)

# 6
call('psql -f %(tmp_sql)s %(dbname)s -U %(dbuser)s' % settings)

# 7
pull_down(settings['osm_url'])
settings['osm_download'] = settings['osm_url'].split('/')[-1]

# 8
osm2pgsql = 'osm2pgsql --utf8-sanitize --prefix %(dbprefix)s --create -d %(dbname)s -U %(dbuser)s'
# for recent versions of osm2pgsql
osm2pgsql += ' --slim'
# for older versions of osm2pgsql
#osm2pgsql += ' -m'
if settings.get('style'):
    osm2pgsql += ' --style %(style)s'
if settings.get('import_bbox'):
    osm2pgsql += ' --bbox %(bbox)s'
osm2pgsql += ' %(osm_download)s'
call(osm2pgsql % settings)

pg_prep = """
update %(dbprefix)s_line set tunnel='yes' where tunnel='true';
update %(dbprefix)s_line set tunnel='no' where tunnel='false';
update %(dbprefix)s_line set tunnel='yes' where tunnel='yel';
update %(dbprefix)s_line set bridge='yes' where bridge='true';

update %(dbprefix)s_line set oneway='yes' where oneway='Yes';
update %(dbprefix)s_line set oneway='yes' where oneway='true';
update %(dbprefix)s_line set oneway='yes' where oneway='1';

CREATE UNIQUE INDEX %(dbprefix)s_polygon_id_idx ON %(dbprefix)s_polygon ( osm_id );
CREATE UNIQUE INDEX %(dbprefix)s_roads_id_idx ON %(dbprefix)s_roads ( osm_id );
CREATE UNIQUE INDEX %(dbprefix)s_line_id_idx ON %(dbprefix)s_line ( osm_id );
CREATE UNIQUE INDEX %(dbprefix)s_point_id_idx ON %(dbprefix)s_point ( osm_id );

create index %(dbprefix)s_polygon_building_idx on %(dbprefix)s_polygon(building);
create index %(dbprefix)s_polygon_amenity_idx on %(dbprefix)s_polygon(amenity);
create index %(dbprefix)s_polygon_landuse_idx on %(dbprefix)s_polygon(landuse);
create index %(dbprefix)s_line_highway_idx on %(dbprefix)s_line(highway);
create index %(dbprefix)s_line_aeroway_idx on %(dbprefix)s_line(aeroway);
create index %(dbprefix)s_line_railway_idx on %(dbprefix)s_line(railway);
create index %(dbprefix)s_line_bridge_idx on %(dbprefix)s_line(bridge);
create index %(dbprefix)s_polygon_leisure_idx on %(dbprefix)s_polygon(leisure);
create index %(dbprefix)s_polygon_aeroway_idx on %(dbprefix)s_polygon(aeroway);
create index %(dbprefix)s_polygon_waterway_idx on %(dbprefix)s_polygon(waterway);
create index %(dbprefix)s_point_place_idx on %(dbprefix)s_point(place);
create index %(dbprefix)s_line_zorder_idx on %(dbprefix)s_line(z_order);
VACUUM ANALYZE;
""" % settings

write_tmp_sql(pg_prep)

# 9
call('psql -f %(tmp_sql)s %(dbname)s -U %(dbuser)s' % settings,fatal=False)

# 10
if path.exists(settings.get('sqlitedb')):
    unlink(settings['sqlitedb'])

# 11 - > N tables
for table in tables:
    pg2sq = 'pgsql2sqlite  -u %(dbuser)s -d %(dbname)s -f %(sqlitedb)s' % settings
    if settings.get('sqlite_select'):
        select = settings['sqlite_select'] % table
    else:
        select = ''' "select * from %s" ''' % table
    pg2sq += ' -t %s -q %s' % (table,select)
    call(pg2sq)    